const FFT = require('fft.js');

// 睡眠阶段计算器类
class SleepStageCalculator {
    calculateSleepStage(feaBas, feaMov, ind1, ind2, ind3) {
        const thrBas = 0.10;
        const thr1 = (feaBas - thrBas) * ind1 + thrBas;
        const thr2 = (feaBas - thrBas) * ind2 + thrBas;
        const thr3 = (feaBas - thrBas) * ind3 + thrBas;

        let sleepStage = 0;

        if (feaMov <= thr1) {
            sleepStage = 1;
        } else if (feaMov > thr1 && feaMov <= thr2) {
            sleepStage = 2;
        } else if (feaMov > thr2 && feaMov <= thr3) {
            sleepStage = 3;
        } else if (feaMov > thr3) {
            sleepStage = 4;
        }

        return sleepStage;
    }
}

// 基础长度队列类，用于计算均值
class BaseLengthQueue {
    constructor(maxLength) {
        this.maxLength = maxLength;
        this.queue = [];
        this.isFull = false;
    }

    addAndComputeMean(value, i) {
        if (!this.isFull) {
            this.queue.push(value);
            if (this.queue.length === this.maxLength) {
                this.isFull = true;
            }
        }

        if (this.isFull && i > 0 && i <= this.queue.length) {
            return this.queue.slice(i - 1).reduce((sum, val) => sum + val, 0) / (this.queue.length - (i - 1));
        }

        return NaN;
    }

    isFullQueue() {
        return this.isFull;
    }
}

// 移动平均滤波器类
class MovingAverageFilter {
    constructor(windowSize) {
        if (windowSize <= 0) {
            throw new Error("窗口大小必须大于0");
        }
        this.windowSize = windowSize;
        this.window = [];
        this.sum = 0;
    }

    addSample(newSample) {
        this.window.push(newSample);
        this.sum += newSample;

        if (this.window.length > this.windowSize) {
            this.sum -= this.window.shift();
        }

        return this.sum / this.window.length;
    }
}

// 固定长度队列类，用于存储EEG数据
class FixedLengthQueue {
    constructor(maxLength, clearLength) {
        if (clearLength >= maxLength) {
            throw new Error("clearLength必须小于maxLength");
        }
        this.maxLength = maxLength;
        this.clearLength = clearLength;
        this.queue = [];
    }

    enqueue(item) {
        if (this.queue.length >= this.maxLength) {
            this.queue.splice(0, this.clearLength);
        }
        this.queue.push(item);
    }

    getQueue() {
        return [...this.queue];
    }

    isFull() {
        return this.queue.length >= this.maxLength;
    }
}

// EEG特征计算类
class EEGSleepFeatureCalculate {
    computePSD(eegData, samplingRate) {
        let n = eegData.length;
        // console.log(`原始EEG数据长度: ${n}`); // 调试：输出原始长度
        if (n <= 1) {
            // console.warn("EEG数据长度不足，填充到2");
            n = 2; // 最小 2 的幂
            eegData = [...eegData, ...Array(n - eegData.length).fill(0)];
        } else {
            // 找到最近的较大 2 的幂
            const log2 = Math.ceil(Math.log2(n));
            n = Math.pow(2, log2);
            // 填充零到 2 的幂长度
            if (eegData.length < n) {
                eegData = [...eegData, ...Array(n - eegData.length).fill(0)];
            }
        }
        // console.log(`调整后的FFT数据长度: ${n}`); // 调试：输出调整后长度

        // 初始化 FFT 输入数组，格式为 [re1, im1, re2, im2, ...]
        const fft = new FFT(n);
        const fftInput = new Array(n * 2).fill(0); // 交替存储实部和虚部
        for (let i = 0; i < n; i++) {
            fftInput[i * 2] = eegData[i] || 0; // 实部
            fftInput[i * 2 + 1] = 0; // 虚部
        }

        // 执行 FFT
        const fftOutput = fft.createComplexArray(); // 创建输出数组
        fft.realTransform(fftOutput, fftInput); // 实数 FFT

        // 计算 PSD
        const psd = new Array(Math.floor(n / 2)).fill(0);
        const frequencies = new Array(Math.floor(n / 2)).fill(0);

        for (let i = 0; i < Math.floor(n / 2); i++) {
            const re = fftOutput[i * 2];
            const im = fftOutput[i * 2 + 1];
            const magnitude = Math.sqrt(re * re + im * im);
            psd[i] = (magnitude * magnitude) / (n * samplingRate);
            frequencies[i] = i * samplingRate / n;
        }

        return { frequencies, psd };
    }

    computePowerInBand(eegData, samplingRate, fLow, fHigh) {
        const { frequencies, psd } = this.computePSD(eegData, samplingRate);
        let power = 0;
        for (let i = 0; i < frequencies.length; i++) {
            if (frequencies[i] >= fLow && frequencies[i] <= fHigh) {
                power += psd[i];
            }
        }
        return power;
    }
}

module.exports = { SleepStageCalculator, BaseLengthQueue, MovingAverageFilter, FixedLengthQueue, EEGSleepFeatureCalculate };
